//
// Created by 67678 on 2023/3/14.
//

#ifndef WEBSERVER_TIMER_H
#define WEBSERVER_TIMER_H

#include <functional>
#include <condition_variable>
#include <chrono>
#include <mutex>
#include <atomic>
#include <set>
#include "nonCopyable.h"

using namespace std;

namespace timer {
struct Time {
    std::chrono::time_point<std::chrono::high_resolution_clock> expire_time;
    std::chrono::microseconds loop_time;
    int tfd = 0;
    int times = 0;
    std::function<void(Time)> callback;

    bool operator<(const Time &rhs) const {
        if (expire_time < rhs.expire_time) return true;
        if (rhs.expire_time < expire_time) return false;
        return tfd < rhs.tfd;
    }
};

class Timer : util::NonCopyable {
public:
    static Timer &getInstance() {
        static Timer t;
        return t;
    }

    void init();

    int addTimer_for(chrono::microseconds, function<void(Time)>, int times = 1);

    int addTimer_until(chrono::time_point<chrono::high_resolution_clock>, function<void(Time)>);

    bool delTimer(int tfd);

    void close();

private:
    bool addTime(const Time &);

    bool delTime(int tfd);

    void loop();

    Timer();

    ~Timer();

    set<Time> times_;
    condition_variable cv_;
    atomic<int> counter_ = 0;
    mutex mx_;
    bool done_ = false;
    chrono::time_point<chrono::high_resolution_clock> next_expire_time_ = chrono::time_point<chrono::high_resolution_clock>::max();
};
}
#endif //WEBSERVER_TIMER_H
